/*
 * Copyright (C) 2012-2013 Michael L.R. Marques
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * Contact: michaellrmarques@gmail.com
 */
package com.jm.jmsql.models;

import com.jm.jmsql.objects.Database;
import com.jm.jmsql.objects.Databases;
import com.jm.jmsql.objects.base.JMSqlObject;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.EventListener;
import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.border.LineBorder;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 *
 * @author Michael L.R. Marques
 */
public class DBXploraTreeModel implements TreeModel {
    
    /**
     * 
     */
    private Databases databases;
    
    /**
     * 
     */
    private EventListenerList listeners;
    
    /**
     * 
     * @param databases 
     */
    public DBXploraTreeModel(Databases databases) {
        this.databases = databases;
        this.listeners = new EventListenerList();
    }
    
    /**
     * 
     * @return 
     */
    @Override
    public Object getRoot() {
        return this.databases;
    }
    
    /**
     * 
     * @param parent
     * @param index
     * @return 
     */
    @Override
    public Object getChild(Object parent, int index) {
        if (((JMSqlObject) parent).isEmpty()) {
            ((JMSqlObject) parent).load();
        }
        return ((JMSqlObject) parent).get(index);
    }
    
    /**
     * 
     * @param parent
     * @return 
     */
    @Override
    public int getChildCount(Object parent) {
        if (((JMSqlObject) parent).isEmpty()) {
            ((JMSqlObject) parent).load();
        }
        return ((JMSqlObject) parent).size();
    }
    
    /**
     * 
     * @param node
     * @return 
     */
    @Override
    public boolean isLeaf(Object node) {
        if (!((JMSqlObject) node).isLoaded()) {
            return false;
        }
        return  ((JMSqlObject) node).isEmpty();
    }
    
    /**
     * 
     * @param path
     * @param newValue 
     */
    @Override
    public void valueForPathChanged(TreePath path, Object newValue) {
        JMSqlObject object = (JMSqlObject) path.getLastPathComponent();
        System.out.println(object);
    }
    
    /**
     * 
     * @param parent
     * @param child
     * @return 
     */
    @Override
    public int getIndexOfChild(Object parent, Object child) {
        return ((JMSqlObject) parent).indexOf((JMSqlObject) child);
    }
    
    /**
     * 
     * @param l 
     */
    @Override
    public void addTreeModelListener(TreeModelListener l) {
        this.listeners.add(TreeModelListener.class, l);
    }
    
    /**
     * 
     * @param l 
     */
    @Override
    public void removeTreeModelListener(TreeModelListener l) {
        this.listeners.remove(TreeModelListener.class, l);
    }
    
    /**
     * 
     * @return 
     */
    public TreeModelListener[] getTreeModelListeners() {
        return this.listeners.getListeners(TreeModelListener.class);
    }
    
    /**
     * 
     * @param <T>
     * @param listenerType
     * @return 
     */
    public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
        return this.listeners.getListeners(listenerType);
    }
    
    /**
     * 
     * @param object 
     */
    public void fireTreeNodesChanged(JMSqlObject object) {
        // Loop through the listeners
        for (TreeModelListener listener : this.getTreeModelListeners()) {
            // Lazily create the event:
            listener.treeNodesChanged(new TreeModelEvent(this, object.getPath(), object.getIndices(), object.toArray()));
        }
    }
    
    /**
     * 
     * @param object 
     */
    public void fireTreeNodesInserted(JMSqlObject object) {
        // Loop through the listeners
        for (TreeModelListener listener : this.getTreeModelListeners()) {
            // Lazily create the event:
            listener.treeNodesInserted(new TreeModelEvent(this, object.getPath(), object.getIndices(), object.toArray()));
        }
    }
    
    /**
     * 
     * @param object 
     */
    public void fireTreeNodesRemoved(JMSqlObject object) {
        // Loop through the listeners
        for (TreeModelListener listener : this.getTreeModelListeners()) {
            // Lazily create the event:
            listener.treeNodesRemoved(new TreeModelEvent(this, object.getPath(), object.getIndices(), object.toArray()));
        }
    }
    
    /**
     * 
     * @param object 
     */
    public void fireStructureChanged(JMSqlObject object) {
        // Loop through the listeners
        for (TreeModelListener listener : this.getTreeModelListeners()) {
            // Lazily create the event:
            listener.treeStructureChanged(new TreeModelEvent(this, object.getPath(), object.getIndices(), object.toArray()));
        }
    }
    
    /**
     * 
     * @author Michael L.R. Marques
     */
    public static final class JMSqlObjectTreeCellRenderer extends JLabel implements TreeCellRenderer {
        
        /**
         * 
         * @param tree
         * @param value
         * @param selected
         * @param expanded
         * @param leaf
         * @param row
         * @param hasFocus
         * @return 
         */
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof JMSqlObject) {
                JMSqlObject object = (JMSqlObject) value;
                setText(object.getName());
                setIcon(object.getIcon());
                setFont(new Font("Arial", Font.PLAIN, 11));
                setBackground(Color.white);
                setBorder(selected ? new LineBorder(Color.black) : null);
                setOpaque(true);
                if (selected) {
                    setBackground(Color.lightGray);
                    setSize(this.getWidth() + 5, this.getHeight());
                }
                //
                if (object instanceof Database) {
                    Database database = (Database) object;
                    if (database.isExternalDatabase() &&
                            !database.isLibraryAvailable()) {
                        setForeground(Color.red);
                        if (selected) {
                            tree.setToolTipText(object.getObjectType().toString() + " cannot find library at location '" + database.getLibrary().getAbsolutePath() + "'");
                        }
                        return this;
                    }
                }
                setForeground(Color.black);
                if (selected) {
                    tree.setToolTipText(object.getObjectType().toString());
                }
                return this;
            }
            return this;
        }
        
    }
    
}
